Add REST endpoint to get content of a file from HEAD of a branch By GET on /projects/<project-name>/branches/<branch>/files/<file>/content it is now possible to retrieve the content of a file from the HEAD revision of a certain branch. The file content is returned as base64 encoded string. This endpoint is useful for integrating tools that need access to certain files, e.g. a tool may need to get the pom.xml from every project. In this case it would be too much overhead to clone each repository just to get this one file from it. Change-Id: I70f294fbcc8a4cc88cd3c1265653cc9870b6433e Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt index c478e79..fed5b04 100644 --- a/Documentation/rest-api-projects.txt +++ b/Documentation/rest-api-projects.txt
@@ -742,6 +742,31 @@ HTTP/1.1 204 No Content ---- +[[get-content]] +Get Content +~~~~~~~~~~~ +-- +'GET /projects/link:#project-name[\{project-name\}]/branches/link:#branch-id[\{branch-id\}]/files/link:rest-api-changes.html#file-id[\{file-id\}]/content' +-- + +Gets the content of a file from the HEAD revision of a certain branch. + +.Request +---- + GET /projects/gerrit/branches/master/files/gerrit-server%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgoogle%2Fgerrit%2Fserver%2Fproject%2FRefControl.java/content HTTP/1.0 +---- + +The content is returned as base64 encoded string. + +.Response +---- + HTTP/1.1 200 OK + Content-Disposition: attachment + Content-Type: text/plain;charset=UTF-8 + + Ly8gQ29weXJpZ2h0IChDKSAyMDEwIFRoZSBBbmRyb2lkIE9wZW4gU291cmNlIFByb2plY... +---- + [[child-project-endpoints]] Child Project Endpoints ----------------------- diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java index c0e3d68..86a3da6 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java
@@ -21,7 +21,6 @@ import com.google.gerrit.server.git.GitRepositoryManager; import com.google.inject.Inject; -import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; @@ -42,17 +41,21 @@ @Override public BinaryResult apply(FileResource rsrc) throws ResourceNotFoundException, IOException { - Project.NameKey project = - rsrc.getRevision().getControl().getProject().getNameKey(); + return apply(rsrc.getRevision().getControl().getProject().getNameKey(), + rsrc.getRevision().getPatchSet().getRevision().get(), + rsrc.getPatchKey().get()); + } + + public BinaryResult apply(Project.NameKey project, String revstr, String path) + throws ResourceNotFoundException, IOException { Repository repo = repoManager.openRepository(project); try { RevWalk rw = new RevWalk(repo); try { RevCommit commit = - rw.parseCommit(ObjectId.fromString(rsrc.getRevision().getPatchSet() - .getRevision().get())); + rw.parseCommit(repo.resolve(revstr)); TreeWalk tw = - TreeWalk.forPath(rw.getObjectReader(), rsrc.getPatchKey().get(), + TreeWalk.forPath(rw.getObjectReader(), path, commit.getTree().getId()); if (tw == null) { throw new ResourceNotFoundException(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java new file mode 100644 index 0000000..29506c9 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java
@@ -0,0 +1,35 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.project; + +import com.google.gerrit.extensions.restapi.RestView; +import com.google.gerrit.server.project.BranchResource; +import com.google.inject.TypeLiteral; + +public class FileResource extends BranchResource { + public static final TypeLiteral<RestView<FileResource>> FILE_KIND = + new TypeLiteral<RestView<FileResource>>() {}; + + private final String path; + + public FileResource(BranchResource rsrc, String path) { + super(rsrc.getControl(), rsrc.getBranchInfo()); + this.path = path; + } + + public String getPath() { + return path; + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java new file mode 100644 index 0000000..389189e --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java
@@ -0,0 +1,48 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.project; + +import com.google.gerrit.extensions.registration.DynamicMap; +import com.google.gerrit.extensions.restapi.ChildCollection; +import com.google.gerrit.extensions.restapi.IdString; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; +import com.google.gerrit.extensions.restapi.RestView; +import com.google.gerrit.server.project.BranchResource; +import com.google.inject.Inject; + +public class FilesCollection implements + ChildCollection<BranchResource, FileResource> { + private final DynamicMap<RestView<FileResource>> views; + + @Inject + FilesCollection(DynamicMap<RestView<FileResource>> views) { + this.views = views; + } + + @Override + public RestView<BranchResource> list() throws ResourceNotFoundException { + throw new ResourceNotFoundException(); + } + + @Override + public FileResource parse(BranchResource parent, IdString id) { + return new FileResource(parent, id.get()); + } + + @Override + public DynamicMap<RestView<FileResource>> views() { + return views; + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java new file mode 100644 index 0000000..48a3ced --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java
@@ -0,0 +1,39 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.project; + +import com.google.gerrit.extensions.restapi.BinaryResult; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; +import com.google.gerrit.extensions.restapi.RestReadView; +import com.google.inject.Inject; +import com.google.inject.Provider; + +import java.io.IOException; + +public class GetContent implements RestReadView<FileResource> { + private final Provider<com.google.gerrit.server.change.GetContent> getContent; + + @Inject + GetContent(Provider<com.google.gerrit.server.change.GetContent> getContent) { + this.getContent = getContent; + } + + @Override + public BinaryResult apply(FileResource rsrc) + throws ResourceNotFoundException, IOException { + return getContent.get().apply(rsrc.getNameKey(), rsrc.getRef(), + rsrc.getPath()); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java index 0ef875e..1b6c410 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
@@ -18,6 +18,7 @@ import static com.google.gerrit.server.project.ChildProjectResource.CHILD_PROJECT_KIND; import static com.google.gerrit.server.project.DashboardResource.DASHBOARD_KIND; import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND; +import static com.google.gerrit.server.project.FileResource.FILE_KIND; import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.restapi.RestApiModule; @@ -33,6 +34,7 @@ DynamicMap.mapOf(binder(), CHILD_PROJECT_KIND); DynamicMap.mapOf(binder(), BRANCH_KIND); DynamicMap.mapOf(binder(), DASHBOARD_KIND); + DynamicMap.mapOf(binder(), FILE_KIND); put(PROJECT_KIND).to(PutProject.class); get(PROJECT_KIND).to(GetProject.class); @@ -57,6 +59,8 @@ get(BRANCH_KIND).to(GetBranch.class); delete(BRANCH_KIND).to(DeleteBranch.class); install(new FactoryModuleBuilder().build(CreateBranch.Factory.class)); + child(BRANCH_KIND, "files").to(FilesCollection.class); + get(FILE_KIND, "content").to(GetContent.class); child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class); get(DASHBOARD_KIND).to(GetDashboard.class);